const axios = require('axios');
const assert = require('assert').strict;

// 基础URL配置
const BASE_URL = 'http://localhost:3000/api';
const AUTH_URL = `${BASE_URL}/auth`;
const MODEL_URL = `${BASE_URL}/models`;

// 测试用户凭据
const TEST_USER = {
    username: 'modelunit',
    password: 'test456',
    email: 'modelunit@example.com'
};

// 全局变量
let accessToken = '';
let testModels = [];

/**
 * 准备测试环境
 */
async function setupTest() {
    console.log('准备测试环境...');

    try {
        // 尝试注册用户
        try {
            await axios.post(`${AUTH_URL}/register`, TEST_USER);
            console.log('测试用户注册成功');
        } catch (error) {
            if (error.response && error.response.status === 409) {
                console.log('测试用户已存在，继续测试');
            } else {
                throw error;
            }
        }

        // 登录用户获取令牌
        const loginResponse = await axios.post(`${AUTH_URL}/login`, {
            username: TEST_USER.username,
            password: TEST_USER.password
        });

        accessToken = loginResponse.data.data.token;
        console.log('测试用户登录成功，获取令牌');

        // 清理之前可能存在的测试模型
        await cleanupTestModels();

        return true;
    } catch (error) {
        console.error('设置测试环境失败:', error);
        return false;
    }
}

/**
 * 清理测试模型
 */
async function cleanupTestModels() {
    console.log('清理现有测试模型...');

    try {
        const response = await axios.get(MODEL_URL, {
            headers: { Authorization: `Bearer ${accessToken}` }
        });

        const models = response.data.data || [];
        for (const model of models) {
            if (model.name.includes('单元测试')) {
                console.log(`删除测试模型: ${model.name} (${model.id})`);
                await axios.delete(`${MODEL_URL}/${model.id}`, {
                    headers: { Authorization: `Bearer ${accessToken}` }
                });
            }
        }
    } catch (error) {
        console.error('清理测试模型失败:', error);
    }
}

/**
 * 测试获取模型列表
 */
async function testGetModels() {
    console.log('\n[测试] 获取模型列表');

    try {
        const response = await axios.get(MODEL_URL, {
            headers: { Authorization: `Bearer ${accessToken}` }
        });

        assert.equal(response.status, 200, '状态码应为200');
        assert.equal(response.data.status, 200, '响应状态应为200');
        assert(Array.isArray(response.data.data), '响应数据应为数组');

        console.log('✅ 测试通过: 获取模型列表');
        return response.data.data;
    } catch (error) {
        console.error('❌ 测试失败: 获取模型列表', error);
        return null;
    }
}

/**
 * 测试创建模型
 * @param {string} name 模型名称
 * @param {string} description 模型描述
 */
async function testCreateModel(name, description) {
    console.log(`\n[测试] 创建模型: ${name}`);

    try {
        const response = await axios.post(MODEL_URL, { name, description }, {
            headers: { Authorization: `Bearer ${accessToken}` }
        });

        assert.equal(response.status, 201, '状态码应为201');
        assert.equal(response.data.status, 201, '响应状态应为201');
        assert(response.data.data.modelId, '响应应包含模型ID');

        console.log('✅ 测试通过: 创建模型');

        // 保存创建的模型ID，用于后续测试
        testModels.push({
            id: response.data.data.modelId,
            name,
            description
        });

        return response.data.data.modelId;
    } catch (error) {
        console.error('❌ 测试失败: 创建模型', error);
        return null;
    }
}

/**
 * 测试更新模型
 * @param {string} modelId 模型ID
 * @param {object} updateData 更新数据
 */
async function testUpdateModel(modelId, updateData) {
    console.log(`\n[测试] 更新模型: ${modelId}`);

    try {
        const response = await axios.put(`${MODEL_URL}/${modelId}`, updateData, {
            headers: { Authorization: `Bearer ${accessToken}` }
        });

        assert.equal(response.status, 200, '状态码应为200');
        assert.equal(response.data.status, 200, '响应状态应为200');
        assert(response.data.message, '响应应包含成功消息');

        console.log('✅ 测试通过: 更新模型');
        return true;
    } catch (error) {
        console.error('❌ 测试失败: 更新模型', error);
        return false;
    }
}

/**
 * 测试删除模型
 * @param {string} modelId 模型ID
 */
async function testDeleteModel(modelId) {
    console.log(`\n[测试] 删除模型: ${modelId}`);

    try {
        const response = await axios.delete(`${MODEL_URL}/${modelId}`, {
            headers: { Authorization: `Bearer ${accessToken}` }
        });

        assert.equal(response.status, 200, '状态码应为200');
        assert.equal(response.data.status, 200, '响应状态应为200');
        assert(response.data.message, '响应应包含成功消息');

        console.log('✅ 测试通过: 删除模型');
        return true;
    } catch (error) {
        console.error('❌ 测试失败: 删除模型', error);
        return false;
    }
}

/**
 * 测试错误场景 - 创建空名称模型
 */
async function testCreateEmptyNameModel() {
    console.log('\n[测试] 创建空名称模型（错误场景）');

    try {
        await axios.post(MODEL_URL, { name: '', description: '测试描述' }, {
            headers: { Authorization: `Bearer ${accessToken}` }
        });

        console.error('❌ 测试失败: 应该拒绝创建空名称模型，但请求成功了');
        return false;
    } catch (error) {
        if (error.response && error.response.status === 400) {
            console.log('✅ 测试通过: 服务器正确拒绝了创建空名称模型');
            return true;
        } else {
            console.error('❌ 测试失败: 创建空名称模型出现意外错误', error);
            return false;
        }
    }
}

/**
 * 测试错误场景 - 更新无效模型
 */
async function testUpdateInvalidModel() {
    console.log('\n[测试] 更新无效模型（错误场景）');

    try {
        await axios.put(`${MODEL_URL}/invalid_id_12345`, { name: '更新测试' }, {
            headers: { Authorization: `Bearer ${accessToken}` }
        });

        console.error('❌ 测试失败: 应该拒绝更新无效模型，但请求成功了');
        return false;
    } catch (error) {
        if (error.response && (error.response.status === 400 || error.response.status === 404)) {
            console.log('✅ 测试通过: 服务器正确拒绝了更新无效模型');
            return true;
        } else {
            console.error('❌ 测试失败: 更新无效模型出现意外错误', error);
            return false;
        }
    }
}

/**
 * 运行所有单元测试
 */
async function runUnitTests() {
    console.log('==== 开始模型API单元测试 ====');

    // 准备测试环境
    const isSetup = await setupTest();
    if (!isSetup) {
        console.error('测试环境设置失败，终止测试');
        return;
    }

    // 测试获取模型列表（初始状态）
    await testGetModels();

    // 测试创建模型
    const modelId1 = await testCreateModel('单元测试模型1', '这是第一个测试模型');
    const modelId2 = await testCreateModel('单元测试模型2', '这是第二个测试模型');

    // 再次测试获取模型列表（应包含新创建的模型）
    await testGetModels();

    // 测试更新模型
    if (modelId1) {
        await testUpdateModel(modelId1, {
            name: '已更新的单元测试模型1',
            description: '这是更新后的第一个测试模型'
        });
    }

    // 测试删除模型
    if (modelId2) {
        await testDeleteModel(modelId2);
    }

    // 测试错误场景
    await testCreateEmptyNameModel();
    await testUpdateInvalidModel();

    // 清理测试数据
    console.log('\n清理所有测试模型...');
    for (const model of testModels) {
        try {
            await axios.delete(`${MODEL_URL}/${model.id}`, {
                headers: { Authorization: `Bearer ${accessToken}` }
            });
            console.log(`删除模型: ${model.name} (${model.id})`);
        } catch (error) {
            console.log(`删除模型失败: ${model.id} - 可能已被删除`);
        }
    }

    console.log('\n==== 模型API单元测试完成 ====');
}

// 执行单元测试
runUnitTests().catch(error => {
    console.error('单元测试过程中出现未捕获的错误:', error);
});